package org.dei.perla.sys.device.fpc;

import org.dei.perla.parser.expressions.Constant;
import org.dei.perla.utils.dataconverter.DataConverter;


import java.lang.reflect.Method;
import java.util.Hashtable;


/**
 * Questa classe contiene tutte le strutture dati necessarie al funzionamento dell'FPC
 * Non e' stata inserita alcuna funzione complementare alla getAttributeByName, in quanto si
 * presuppone che il valore degli attributi contenuti nelle strutture dati sia impostato
 * esclusivamente dalla funzione deserializeData, la quale deserializza lo stream di Byte
 * in arrivo dal dispositivo fisico e modifica i valori delle strutture aggiornandone il contenuto
 * con i dati attuali. 
 * TODO: Valutare se l'assunzione che una setAttributeByName non serva sia corretta
 */
public abstract class FPCDataStructure {
	protected AbstractData root;
	
	protected FPCDataStructure(){
	}
	/**
	 * Metodo da utilizzarsi per recuperare il valore di un singolo attributo
	 * a partire dal nome di questo. Nel caso il nome dell'attributo non appartenga
	 * all'FPC verra' restituito null.
	 * @param parName nome dell'attributo richiesto
	 * @return Valore dell'attributo richiesto. Viene restituito null nel caso l'FPC
	 * non contenga l'attributo richiesto
	 * @throws Exception 
	 */
	public abstract Constant<?> getAttributeByName(String parName) throws Exception;
	
	/**
	 * Questo metodo consente di popolare una delle strutture dati presenti nella classe
	 * a partire dallo stream di dati ricevuto dal dispositivo fisico di cui l'FPC e' l'astrazione
	 * @param parStructureIdentifier identificatore della classe da popolare
	 * @param parRawDataArray array contenente i dati con cui caricare la classe
	 */
	public void deserializeData(String parStructureIdentifier, Byte[] parRawDataArray) {
		Object structure = this.getDataStructure(parStructureIdentifier);
		
		if (structure == null) {
			throw new IllegalArgumentException("La struttura dati " + parStructureIdentifier + 
			" non e' stata trovata!");
		}
		DataConverter.fromByteArray(structure, parRawDataArray);
	}
	
	/**
	 * Questo metodo permette di convertire una struttura dati in un array di Byte utilizzabile
	 * per l'invio su rete
	 * @param parStructureIdentifier identificatore della struttura dati da serializzare
	 * @return array di byte corrispondente alla serializzazione della classe
	 */
	public Byte[] serializeData(String parStructureIdentifier) throws IllegalArgumentException {
		Object structure = this.getDataStructure(parStructureIdentifier);
		
		if (structure == null) {
			throw new IllegalArgumentException("La struttura dati " + parStructureIdentifier + 
					" non e' stata trovata!");
		}
		return DataConverter.toByteArray(structure);
	}
	
	/**
	 * Metodo per il recupero di una struttura dati memorizzata all'interno della classe.
	 * Puo' essere implementato come una semplice tabella di lookup. L'identificatore puo'
	 * essere il nome stesso della struttura dati da recuperare
	 * @param parStructureIdentifier identificatore della struttura dati da recuperare
	 * @return struttura dati richiesta. Nel caso l'identificatore non corrisponda a nessuna
	 * struttura dati presente nella classe deve essere restituito null
	 */
	protected abstract Object getDataStructure(String parStructureIdentifier);
}
